\documentclass[a4paper,10pt]{article}
\usepackage{graphicx}

\title{Gedistribueerde Systemen\\\small Verslag Team 8}
\author{Harm Dermois, Wadie Assal \& Ravish Gopal\\\small}

\begin{document}
\maketitle

\includegraphics[width=12cm]{chat.png}

\newpage
\tableofcontents
\newpage
\section{Inleiding}
De verslag beschrijft de bouw van een server die kan functioneren in 
een gedistribueerd chatnetwerk waarin communicatie verloopt via UDP. 
Het netwerk opereert volgens een protocol van opvolgende berichten.
\\\\ 
Het protocol werkt als volgt:
het netwerk kent een boomstructuur.
Dit betekent dat elke server slechts een 
verbinding heeft met zijn parent server, maar meerdere verbindingen kan hebben 
die door (andere) child servers met hem worden aangegaan. Het is belangrijk
dat de boomstructuur behouden blijft en er geen cykels ontstaan, omdat er dan
een kans bestaat dat berichten blijven rondgaan in de cykel en hun bestemming
niet bereiken. Het protocol heeft acties die voorzien in de opbouw en het 
behoud van de boomstructuur.
Om de status van het netwerk en de verbindingen bij te houden worden alle gegevens 
opgeslagen in een datastructuur.\\\\
Elke server heeft dus 4 soorten verbindingen:
\begin{itemize}
\item verbinding met parent: \'e\'en verbinding
\item verbinding met control server: \'e\'en verbinding
\item verbinding met childservers: veel verbindingen
\item verbinding naar clients: veel verbindingen
\end{itemize}
Er zijn zeven berichttypes. Client-server, server-client en server-server
worden gebruikt voor het onderhoud van het netwerk en voor het versturen
en bezorgen van de berichten van de ene client naar de andere. Controlserver-server
en server-controlserver berichten worden gebruikt voor het toevoegen van
een nieuwe server aan het al bestaande netwerk, of voor het hergroeperen van
de servers als er een server wegvalt. Ook zijn er controlserver-client en client-controlserver
berichten, deze zijn voor onze implementatie niet zo van belang.
Het protocol is beperkt tot basis functionaliteit. Dat wil zeggen 
dat clients zich kunnen aanmelden op een willekeurige server, en dan 
overal in het netwerk zichtbaar zijn. Clients kunnen met elkaar 
praten over het netwerk. Servers kunnen verbinding met elkaar en/of 
met de controlservermaken. Servers kunnen elkaar uit het netwerk 
verwijderen als er iets niet klopt in de berichten. Servers kunnen 
clients verwijderen uit het netwerk.

\section{Ontwerpkeuzes}
Wij hebben ons zoveel mogelijk gehouden aan onze plan van aanpak. 
Echter is er wel tot twee keer toe wijzigingen aangebracht in de 
structuur van data opslag. Aanvankelijk was er \'e\'en klasse waarin 
Er in \verb|Vector|lijsten de verbinding gegevens wordt bijgehouden. 
Dat is later opgesplitst in een parentklasse \verb|DataStorage| en 
kind klasses \verb|DataServer| en \verb|DataClient|. Maar om het 
gebruik van de data makkelijker te maken in de \verb|Pinger| en de
\verb|MessageHandler| hebben wij gekozen voor de klasse 
\verb|DataStorage|, waarin de \verb|Vector|lijsten worden 
bijgehouden, en de klasses \verb|ConnectedDevices| en \verb|Clients|. 
Dit stelt ons in staat om makkelijker bij de juiste data te komen. 
In de \verb|Pinger| ben je bijvoorbeeld slechts ge\"{i}nteresseerd in 
de apparaten (servers en/of clients) die direct aan de server zelf 
verbonden zijn. Ook heeft de logging klasse een hulpklasse gekregen 
om de logoutput wat leesbaarder te maken.
\\
De keuze voor Java als programeertaal is niet slecht bevallen. Deze taal 
kenden wij het best en gezien het programmeren op zich al genoeg tijd 
kostte, zou er weinig tijd zijn om een nieuwe taal te leren.
\\
De planning was in eerste instantie prima. Maar omdat we niet meteen in 
het begin getest hadden met de controlserver, zijn we later op problemen 
gestuit, waardoor we ons niet aan de planning konden houden. De 
werkverdeling was volgens plan, waarbij Wadie zich concentreerde op de 
\verb|DataStorage|, Harm de \verb|MessageCreator, Listener en Main| 
implementeerde, Ravish de \verb|Logger en Pinger| maakte en Harm en 
Ravish de \verb|MessageHandler| verzorgden. 
Uiteindelijk bleven we aan elke klasse wel sleutelen, omdat niet alles 
soepel en volgens plan werkte. Daarom zijn we uitgelopen op de planning.

\section{Ontwerp}
Met de bovengenoemde wijziging zijn wij op het volgende ontwerp 
uitgekomen.\\\\
\includegraphics[width=12cm]{design.jpg}

\section{Implementatie}
Het programma werkt als volgt: \\
De \verb|Main| klasse start de \verb|Listener, MessageHandler en Pinger|. 
Volgens protocol wordt een bericht gestuurd naar de \verb|controlserver|, waarna 
de \verb|server| ofwel een \verb|parentserver| toegewezen krijgt, ofwel als root wordt 
aangewezen. De \verb|Listener| luistert inkomende berichten af en zet deze 
in de queue van de \verb|MessageHandler|. De \verb|MessageHandler| haalt 
berichten uit de queue, plaatst eventueel data in de \verb|DataStorage| 
en bepaalt aan de hand van het berichttype hoe het 
bericht moet worden afgehandeld. Waar nodig wordt de \verb|MessageCreator| 
aangeroepen om een nieuw bericht te versturen aan de juiste ontvangers. 
Belangrijke handelingen en foutafhandelingen worden gelogd per klasse. Om 
bij te houden welke \verb|servers| in het netwerk actief zijn, verstuurt de \verb|Pinger| 
klasse om de 10 seconden een \verb|ping| bericht naar alle verbonden apparaten en 
wacht hij het antwoord af. Bij 3 keer geen of te laat bericht wordt het apparaat 
verondersteld dood te zijn en wordt deze uit het netwerk verwijderd.
\\\\
Hier volgt een beschrijving van de klasses en hun functies.
\subsection{Main}
De main hier begint de server. De threads op die nodig zijn 
voor het programma worden hier opgestart. Dat er zijn
in dit geval 3 threads: de \verb|listener|, de \verb|messagehandler| en 
\verb|de pinger|. Ook wordt er een logger en een \verb|DataStorage| instantie 
aangemaakt.
\\
\begin{itemize}
\item \textbf{makeServerIdent} - Hier wordt de server indentificatie gemaakt. Er wordt maar een beperkt aantal ASCII karakters gebruikt om deze unieke server identificatie uit op te bouwen.
\item \textbf{main} - Het mainprogramma dat alle threads opstart om de server te runnen, zoals hierboven beschreven.
\end{itemize}

\subsection{Listener}
De listener vang inkomende berichten op en roept dan de \verb|MessageCreator| 
aan, die het in het de \verb|message queue| zet. 
 
\subsection{MessageCreator}
Deze methodes uit deze klasse worden alleen aangeroepen door de
\verb|MessageHandler| of de \verb|Pinger| die de opdracht geeft om berichten 
naar de gespecifeerde bestemmingen te sturen.
\\
\begin{itemize}
\item \textbf{intToByteArray} - Converteer een int naar byte array, is een hulp functie voor de \verb|msgPacker|.
\item \textbf{msgPacker} - Bouw de header op in byte formaat, volgens protocol.
\item \textbf{msg110-msg701} - methodes per berichttype voor het versturen van berichten met eventuele parameters, volgens protocol.
\end{itemize}

\subsection{MessageHandler}
De messagehandler haalt de messages uit de queue en kijkt wat hij hiermee 
moet doen. Hiermee roept hij de goede methode aan in de message creator die 
dan de message opstuurt naar de message gespecificeerde device in uit de 
datastorage. Enige uitzondering is de control server.
\\
\begin{itemize}
\item \textbf{byteArrayToString} - Converteert een byte array naar een String, hulp functie.
\item \textbf{addMessageToMessageQueue} - Voegt berichten toe aan de te versturen message queue.
\item \textbf{getMessageFromMessageQueue} - Haalt berichten uit de message queue op.
\item \textbf{getMessageFromDatapacket} - Pakt een Datapacket uit om het bericht eruit te halen.
\item \textbf{handle} - Handelt berichten af op basis van berichttype. Elk berichttype kent zijn eigen afhandeling. Door middel van een switch() wordt bepaald welke afhandeling nodig is, waarna de juiste methode 
\verb|msg110-msg701| wordt aangeroepen.
\item \textbf{msg110-msg701} - Handelen hun berichttype af en voeren \verb|DataStorage| acties uit en/of sturen berichten via de \verb|MessageCreator|.
\item \textbf{run} - Thread die inkomende berichten afhandelt.
\end{itemize}

\subsection{DataStorage}
In deze klasse worden \verb|Vector|lijsten bijgehouden met 
\verb|ConnectedDevices| en \verb|Clients| objecten (hieronder beschreven).
Er zijn CRUD-methodes voor deze lijsten. Dat wil zeggen dat er nieuwe objecten 
aan de lijst kunnen worden toegevoegd, objecten kunnen worden opgehaald, 
ge\"update en/of verwijderd. Ook zijn er een paar hulp functies die 
hieronder worden beschreven. 
\begin{itemize}
\item \textbf{checkDuplicateNames} - Controleert op dubbele namen. Returnt true als naam al bestaat. Nodig bij het controleren van aanmelding of naamwijziging van \verb|clients|.
\item \textbf{getClientsConnectedToServer} - Haalt alle \verb|clients| op die verbonden zijn aan een server. Nodig bij het afhandelen van het uitvallen van een \verb|server|.
\item \textbf{getClientsNotConnectedToServer} - Haalt alle \verb|clients| op die \textbf{niet} verbonden zijn aan een server. Nodig voor het versturen van berichten aan alle andere \verb|clients|.
\item \textbf{removeClientsConnectedToServer} - Verwijderd alle \verb|clients| die verbonden zijn aan een server. Nodig bij het afhandelen van het uitvallen van een \verb|server|.
\end{itemize}

\subsection{ConnectedDevices}
Deze klasse bevat methodes specifiek voor apparaten die direct aan de 
\verb|server| verbonden zijn. Dat zijn andere \verb|servers| (hops) of 
\verb|clients|. Met de methodes kunnen de apparaatgegevens opgevraagd 
of gemanipuleerd worden.

\subsection{Clients}
Deze klasse bevat methodes specifiek voor \verb|Clients|. Elke \verb|client| object heeft 
een \verb|ConnectedDevices| object: ofwel een \verb|server| (hop) of de 
\verb|client| zelf als hij direct aan de server verbonden is. 
Met de methodes kunnen de \verb|client|gegevens opgevraagd of gemanipuleerd 
worden.

\subsection{Pinger}
De pinger thread kijkt welke apparaten actief zijn. Voor alle geregistreerde 
apparaten wordt gecontroleerd of hun laatste pingtijd ouder is dan het ping 
interval. Als dat het geval is zal er een ping bericht gestuurd worden via 
de MessageCreator en wordt de ping count verhoogd. Als de pingtijd 
verstreken is, wordt er gekeken naar de pongtijd. Als beide verstreken zijn, 
krijgt het apparaat 3 kansen om op tijd te pongen. Als de tijden verstreken 
zijn en er 3 keer gepingd is, zal het apparaat verwijderd worden en zal het 
bijbehorende bericht verstuurd worden naar de andere apparaten. 

\subsection{Logging}
Een klasse voor het aanmaken en initialiseren van loggers vanuit een 
willekeurige klasse. Bij het initialiseren wordt er een bestand aangemaakt 
als deze niet bestaat (\verb|src/log/Klassenaam.log|)
\begin{itemize}
\item \textbf{createLogger} - Maak een Logger instantie.
\item \textbf{initLogger} - Initialiseer de logger instantie, zodat er een bestand eraan wordt gekoppeld of wordt aangemaakt.
\item \textbf{flushLogger} - Verwijder de inhoud van een logfile.
\end{itemize}

\subsection{CustomFormatter}
Hulpklasse voor de logger om logberichten leesbaarder te maken.
\begin{itemize}
\item \textbf{format} - Bouw de nieuwe logmessage op dmv een object array waarin staan: tijd, klassenaam, methode, loglevel en het bericht. 
\item \textbf{toStr} - Om de output van de logger wat leesbaarder te maken worden de klasses en de methode namen aangevuld tot een vaste lengte.
\end{itemize}


\section{Gebruik}
Het programma is te verkrijgen d.m.v. een checkout van onze 
repository: \\\\
\verb|svn checkout http://gedistsys.googlecode.com/svn/trunk/dsc gedistsys-read-only|\\
\\
De code bevindt zich in de map \verb|/dsc/src/dsc/| en kan gecompiled 
worden met \verb|java -source 5 *.java|. Om het programma te runnen 
dient er vanuit de \verb|/dsc/src/| map het commando 
\verb|java dsc/Main| uitgevoerd te worden.


\section{Conclusie en Reflectie}
Het is goed mogelijk om met UDP en een goed protocol een netwerk van 
chatservers te bouwen. Alhoewel er in het protocol rekening moet worden 
gehouden met het risico van verlies van berichten door het gebruik van 
UDP. Nu was er een berichtvolgnummersysteem waarbij voor elke 
communicatielijn volgnummers voor de berichten wordt bijgehouden. 
Zodra de sequentie niet klopt wordt de versturende server uit het 
netwerk gehaald en dient hij opnieuw verbinding te maken. Dit is niet 
zo fout  tolerant. Het zou beter zijn om per server een buffer van 
berichten bij te houden, waarbij in het geval van een gemist bericht, 
dat bericht opnieuw kan worden verzonden.
\\\\
Wij zijn een aantal problemen tegengekomen. De berichtafhandeling 
bleek nogal lastig, zeker als het ging om het correct 
verwerken van een uitgevallen server en de aan hem verbonden 
clients. Wij keken eerst niet zo goed 
naar wie wij allemaal berichten hadden verstuurd, en kregen zodoende 
te maken met dubbele berichten.\\
We hebben ook onze manier van data opslag moeten aanpassen, omdat het 
aanvankelijke gekozen systeem zich niet goed leende voor het programma 
(zoals beschreven in paragraaf 'Ontwerpkeuzes').
\\\\
De control server was 
niet altijd (goed) bereikbaar, waardoor we minder (goed) konden testen. 
Het is erg vervelend dat de controlserver nog niet af was voor dat er met 
met het programmeren werd begonnen. Zelfs op de dag dat het programma 
ingeleverd diende te worden was de controlserver slecht bereikbaar en 
moest een alternatieve controlserver worden aangesproken.
\\\\
De problemen zouden(eerder) kunnen 
worden verholpen als wij gebruik hadden gemaakt van unittests. We zouden 
voor alle berichtafhandelingen en client-server en server-server 
interactie tests kunnen hebben gemaakt, om de uitkomsten van de 
interactie te controleren. Echter hadden wij niet voldoende tijd 
hiervoor.

%ik denk dat dit erin moet.
Ook vonden wij het protocol niet altijd even duidelijk. Bij het
samen werken van de server en de chat was het niet altijd eenduidig hoe
je de berichten binnen zou krijgen en hoeze precies afgehandelt moeten 
worden. Ik vind dat je een server helemaal los van client had moeten 
kunnen maken, maar in sommige gevallen moest je echt kijken hoe en wat
de chat precies deed. Dit werd wel goed opgelost door de rawlog die 
in de chat aanwezig was, maar met een wat duidelijkere protocol waar 
misschien ook wat meer voorbeelden in te vinden zijn. Zou deze 
functionaliteit niet zo esentieel zijn. Zo zijn er een paar andere dingen
in het protocol die wat beter voor ons uitgekauwt mochten zijn, maar 
misschien was het de bedoeling om wat dingen voor eigen interpretatie open
te houden. 

We hebben er voor gekozen de berichten die we binnen krijgen eerst in een 
queue te stoppen en dan af te handelen, maar bij nader inzien is dit 
misschien niet de beste oplossing bij het gebruik van UDP. Het gebruik
van deze queue is om de reliability van de server te vergroten, maar
UDP is toch best effort dus is het misschien beter om gewoon alleen te
behandelen wat we kunnen en gewoon de listener laten wachten tot dat. We
de message hebben behandelt totdat we de volgende message hebben toegevoegd.

Ook sturen wij geen pings naar de control-server. Dit leek ons overbodig omdat
de control-server zelf ook om de 10 seconde een ping stuurt. Ook heeft de
control-server geen functie binnen het netwerk. Het enige wat er kan gebeuren
wanneer de control-server uitvalt is dat er geen server meer kunnen connecten 
of reconnecten, maar als het netwerk stabiel is en de clienten de servers
zelf kunnen vinden is er geen reden waarom de control-server niet mag
uitvallen.

Ik denk dat java een goede keuze was voor het implementeren van deze server. 
In java hebben ze thread safe datastructuren en datagrampakketten zijn 
makkelijk te gebruiken, maar door een domme fout hadden we veel problemen met 
ontvangen van berichten, omdat we wel nieuwe paketten binnen kregen. Maar
wat we fout deden is dat de pakketen eerst steeds naar de zelfde buffer wezen 
waardoor alleen het laatste bericht werd behandelt wanneer er snel berichten 
binnen kwamen. 

Tijdens de demo gingen er wel wat dingen fout. We hadden de dag daarvoor
nog een aantal dingen veranderd vooral voor de leesbaarheid van de code, maar 
in het overzetten van de code waren er wat fout in geslopen. Wat er ook mis
ging op de demo was dat we sommige berichten dubbel opstuurde. Dit kwam
omdat we in eerste instantie dachten dat we bij een bericht die \# all bevatte
er handmatig naar alle clienten gestuurd moest worden, maar in werkelijkheid
alleen naar de servers en clienten die aan ons verbonden waren. Dit zorgde
ervoor dat als er op een als er een bericht werd verstuurd vanaf een server
die van ons werd naar \# all dat er berichten x aantal berichten werden
gestuurd met x het aantal clienten die bij een server verder op zitten. Dus
Dit zorgde ervoor dat als er bijvoorbeeld drie clienten aan een andere server
vast zat dat het bericht drie keer werd verstuurd naar de server. 
% nog iets zeggen over de 604 als ik die klaar heb.
\\
Omdat er altijd wel servers van anderen online waren, hebben we goed kunnen
testen met andere servers. Bij de demo bleef onze server goed draaien bij de
laatste test. Alleen bij de stress test ging er wat fout bij het ophalen van 
devices. Ik denk dat daar ook de zwakte ligt van onze server. We moeten elke keer
afvangen wanneer er een client of device niet gevonden kan worden. Vooral bij
de pinger kan dit goed mis gaan. In onze implementatie hebben we per device
een eigen timer voor het versturen van pings. Al deze devices worden afgelopen
in de pinger en gekeken of er al 10 seconde voorbij zijn. Dit blijft hij 
constant doen, maar in een andere thread kan het device al verwijderd tijdens 
dit checken waardoor dit soort errors kunnen optreden. Dit kan misschien 
opgelost worden door gewoon om de tien seconde naar iedereen een ping te 
maakt niet uit of hij al aanwezig of net is aangemeld. Dit geeft ook wat 
minder overhead. Maar wij probeerde het zo precies mogelijk uitvoeren en 
dit leek ons de beste oplossing. 
\\
Voor de samenwerking leek het ons onvoldoende om elkaar alleen te zien tijdens 
de geroosterde practicumuren, daarom hadden wij afgesproken om elke vrijdag een 
extra sessie te doen. Soms gingen sessies niet door, waardoor we niet elke week 
twee practicumsessies hadden. We moesten daardoor eerst door overleg op dezelfde 
pagina komen, waardoor het opstarten van de practicumsessies soms moeizaam ging.
Afgezien daarvan hadden we een goede samenwerking en hebben we samen een werkende 
server geprogrammeerd.
\\
Zoals eerder aangegeven is het een goede keuze geweest om voor de meest bekende 
programmeertaal te kiezen, Java in ons geval. Als wij een andere programmeertaal 
hadden gekozen waren we waarschijnlijk meer tijd kwijt geraakt aan het leren van 
de taal en hadden we problemen gehad het programma af te krijgen.
\\\\
De les die wij uit dit practicum kunnen trekken is dat bij het maken van grotere 
programma's het beter is om eerst goed over de structuur na te denken en een de 
functionaliteiten eerst goed in kaart te brengen, alvorens je begint te 
programmeren. Het maken van een Functioneel Ontwerp en misschien zelfs een 
Technisch Ontwerp zou waardevol zijn.
\end{document}
